<template>
    <div class="max-container">
    <el-container class="editor-container" id="editor">
      <el-header class="no-padding toolbar no-select" height="35px">
        <ul class="ui-ul-inline-block">

          <!-- <li @click="codeBlock.isShow = true">
            <img src="@/assets/images/icon-shot_20PX@2x.png" alt="" />
            <p class="tip-title">截屏</p>
          </li> -->
          <li class="ui-file-box" @click="$refs.restFile.click()">
            <img src="@/assets/images/icon-pic_20PX@2x.png" alt="" />
            <p class="tip-title">图片</p>
          </li>
          <li @click="$refs.restFile2.click()">
            <img src="@/assets/images/icon-foder_20PX@2x.png" alt="" />
            <p class="tip-title">文件</p>
          </li>
          <li @click="historyShow" :class="{ active: this.history }">
            <img src="@/assets/images/icon-histroy_20PX@2x.png" alt="" />
            <p class="tip-title">消息记录</p>
          </li>
        </ul>
        <form enctype="multipart/form-data" style="display: none" ref="fileFrom">
          <input id="upload-image" type="file" ref="restFile" accept="image/gif,image/jpeg,image/png,image/webp"
            multiple @change="uploadImageChange" />
          <input id="upload-file" type="file" ref="restFile2" accept="*" multiple @change="uploadFileChange" />
        </form>
      </el-header>
      <!-- <div>{{sessionInfo}}</div> -->
      <el-main class="no-padding textarea">
        <!-- 群聊时才显示@组件 -->
        <vue-tribute :options="tributeOptions" >
          <div ref="textarea" id="textarea" class="edit-textarea" @paste="pasteImage" @drag="dragPasteImage" rows="5"
            :placeholder="请输入" @keydown="keydownEvent($event)" @input="inputEvent($event)" @contextmenu="onContextMenu"
            @tribute-no-match="noMatchFound" contenteditable="true" />
        </vue-tribute>
        <div class="send-button no-select">
          <span @click="sendMsg">发送消息</span>
        </div>
      </el-main>
    </el-container>
  </div>

</template>

<script>
import { mapState, useStore } from "vuex";
import { ref, inject } from "vue";
import { ClickOutside as vClickOutside } from "element-plus";
import VueTribute from "vue-tribute";
import { handleMemberName } from "@/utils/chat";
import { isEmpty } from "@/utils/string";
import { ACTIVE_MSG_COPY_ITEM } from '@/store/actiontypes'
const REPLY_TAG = 'replyTag'  //如果这个是回复消息的标记
export default {
  directives: {
    vClickOutside: {
      mounted(el, binding) {
        function eventHandler(e) {
          if (el.contains(e.target)) {
            return false;
          }
          // 如果绑定的参数是函数，正常情况也应该是函数，执行
          if (binding.value && typeof binding.value === "function") {
            binding.value(e);
          }
        }
        // 用于销毁前注销事件监听
        el.__click_outside__ = eventHandler;
        // 添加事件监听
        document.addEventListener("click", eventHandler);
      },
      beforeUnmount(el) {
        this.clearReplyMsgItem()
        // 移除事件监听
        document.removeEventListener("click", el.__click_outside__);
        // 删除无用属性
        delete el.__click_outside__;
      },
    },
  },
  setup(props, context) {
    console.log("输入框消息")
    const store = useStore()
    const imageUrl = ref("");
    const handleAvatarSuccess = (res) => {
      console.log(res);
    };
    const beforeAvatarUpload = (res) => {
      console.log(res);
    };

    return {
      vClickOutside,
      imageUrl,
      handleAvatarSuccess,
      beforeAvatarUpload,
    };
  },
  name: "MeEditor",
  components: {
    VueTribute,
  },
  props: {
    // 对话相关参数
    params: {
      type: Object,
      default: function () {
        return {
          nickname: "",
        };
      },
    },
    sessionInfo: {
      type: Object,
      default: function () {
        return {};
      },
    },
  },
  computed: {
    ...mapState({

    }),
    //@ item选中的模板
    tributeOptions() {
      return {
        trigger: "@",
        requireLeadingSpace: false,
        values: this.atValues,
        selectTemplate: function (item) {
          return (
            '<span contenteditable="false">' +
            "@" +
            item.original.value +
            "</span>"
          );
        },
      };
    },
  },
  data() {
    return {
      history: false,
      buttonRef: ref(),
      // popoverVisible:true,
      flag: false,
      inputTextContent: "",//输入的文本消息
      // 图片查看器相关信息
      imageViewer: {
        isShow: false,
        file: null,
      },

      codeBlock: {
        isShow: false,
        editMode: true,
      },

      // 上次发送消息的时间
      sendtime: 0,

      // 发送间隔时间（默认1秒）
      interval: 1000,
      fileValue: "",
      atValues: [],

    };
  },
  mounted() {
    console.log("输入框消息mounted")
  },
  watch: {
    sessionInfo: {
      handler() {
        this.history = false;
        this.$nextTick(() => {
          this.$refs.textarea.textContent = ''
          const textareaHtml = this.editMap[this.sessionInfo.targetId]
          if (!!textareaHtml) {
            if (this.$refs.textarea) {
              this.$refs.textarea.innerHTML = textareaHtml
            }
          }
        })
      },
      immediate: false, //第一次不打开 也就是确保在mounted方法调用之后
    },
    groupMemberList(n) {
      this.handleAtValue();
    },
    //如果右键了回复 地址变化
    '$store.state.chat.msgRecordCopyItem': {
      handler(newVal) {
        if (newVal) {
          const targetId = this.sessionInfo.targetId
          if (newVal[targetId]) {
            const val = newVal[targetId]
            if (val.messageType) {
              let replyContent = ''
              switch (val.messageType) {
                case 'QX:TxtMsg': //如果是文本消息
                  //${this.getChatItemUserInfo(val).nickname}
                  //console.log("sessionList", this.sessionInfo)
                  replyContent = `${val.text.content}\n`;
                  break;
                case 'QX:ImgMsg': //如果是图片消息
                  replyContent = `[${this.$t("pictureMsg")}]\n`;
                  break;
                case 'QX:FileMsg': //文件消息
                  replyContent = `[${this.$t("fileMsg")}]\n`;
                  break;
                case 'QX:VcMsg': //视频文件消息
                  replyContent = `[${this.$t('videoFileMsg:')}]\n`;
                  break;
                case 'QX:AcMsg': //音频文件消息
                  replyContent = `[${this.$t("audioFileMsg")}]\n`;
                  break;
                case 'QX:Reply': //回复消息 
                  //第一步拿到消息item的reply对象
                  //不改变原始内存地址
                  const itemContent = JSON.parse(JSON.stringify(val));
                  const replyObject = itemContent.reply
                  //回复发送者 也就是自己 要发出去的消息
                  const msg = JSON.parse(replyObject.msg)
                  const reply = JSON.parse(replyObject.reply)
                  replyContent = `${reply.text.content}\n`;
                  break;
                default:
                  replyContent = `[${this.$t("unknow")}]\n`;
                  break;
              }
              const replyMsgDom = document.createElement("div")
              const sendNameDom = document.createElement("div")
              sendNameDom.innerText = this.getChatItemUserInfo(val).nickname + ":\n"
              sendNameDom.setAttribute("contenteditable", "false")
              const replyMsgContentDom = document.createElement("div")
              replyMsgContentDom.innerText = replyContent
              replyMsgContentDom.style.webkitLineClamp = '2'
              replyMsgContentDom.style.boxOrient = 'vertical'
              //replyMsgContentDom.style.display = '-webkit-box' //会影响省略号
              replyMsgContentDom.style.textOverflow = 'ellipsis'
              replyMsgContentDom.style.whiteSpace = 'nowrap'
              replyMsgContentDom.style.width = '70%'
              replyMsgContentDom.style.overflowX = "hidden"
              replyMsgContentDom.setAttribute("contenteditable", "false")
              replyMsgDom.appendChild(sendNameDom)
              replyMsgDom.appendChild(replyMsgContentDom)
              replyMsgDom.style.backgroundColor = '#F0F2F5'
              replyMsgDom.style.borderRadius = '2px'
              replyMsgDom.style.opacity = 1
              replyMsgDom.style.paddingTop = '4px'
              replyMsgDom.style.paddingLeft = '11px'
              replyMsgDom.style.marginBottom = '20px'
              replyMsgDom.setAttribute(REPLY_TAG, REPLY_TAG)
              replyMsgDom.setAttribute("contenteditable", 'false') //这里整体不可编辑 同时也是为了统一样式

              this.$refs.textarea.appendChild(replyMsgDom)
              const br = document.createElement("br")
              br.style.height = '1px'
              this.$refs.textarea.appendChild(br)
              this.$refs.textarea.focus()
              this.editMap[this.sessionInfo.targetId] = this.$refs.textarea.innerHTML
            }
          }
        }
      },
      deep: true,
      immediate: false, //第一次不用执行
    }
  },
  methods: {
    /**
     * 控制输入框 每次如果点击 了发送按钮 要在store里面清除map缓存
     */
    clearEditMapValueBySessionId() {
      //拿到store的map ==从computed里面获取
      this.editMap[this.sessionInfo.targetId] = null
    },
    /**
     * 每次发送消息清空 选中的回复item
     */
    clearReplyMsgItem() {
      //删除完了 要处理 右键的时候 回复要能展示
      const copyItem = {}
      const currentTargetId = this.sessionInfo.targetId ? this.sessionInfo.targetId : ''
      copyItem[currentTargetId] = ''
      const replaceObject = Object.assign(this.msgRecordCopyItem, copyItem)
      this.$store.commit(ACTIVE_MSG_COPY_ITEM, { msgRecordCopyItem: replaceObject })
    },
    getChatItemUserInfo(item) {
      if (item.from === this.userId) {
        return {
          nickname: this.userInfo.userName,
        };
      }
      // 私聊
      if (item.sendType === "PRIVATE") {
        return {
          nickname: this.sessionInfo.name
        };
      } else {
        const groupMemberList = this.groupMemberList;
        const user = groupMemberList.find((gm) => gm.userId === item.from);
        if (user) {
          return {
            nickname: handleMemberName(user),
          };
        }
        return {
          nickname: item.from
        };
      }
    },
    handleAtValue() {
      let res = this.groupMemberList
        .filter((item) => item.userId !== this.userId)
        .map((item) => {
          return {
            key: handleMemberName(item),
            value: handleMemberName(item),
          };
        });
      const temp = this.groupMemberList.find(
        (item) => item.userId === this.userId
      );
      if (temp?.isLeader) {
        res.unshift({
          key: this.$t("everyone"),
          value: this.$t("everyone"),
        });
      }
      this.atValues = res;
    },
    // 右键
    onContextMenu(ev) {
      // 阻止默认行为
      ev.preventDefault();
      // 获取鼠标位置
      const client = {
        x: ev.clientX,
        y: ev.clientY,
        cutText: this.$t("cut"),
        copyText: this.$t("copy"),
        pasteText: this.$t("paste"),
      };
      // 把鼠标位置发送到主进程
      this.$ipcInvoke(ipcApiRoute.contextMenu, client);
    },
    //历史记录
    historyShow() {
      this.history = !this.history;
      this.$emit("historyShow", this.history);
    },
    //复制粘贴图片回调方法
    pasteImage(e) {

    },
    //输入事件
    inputEvent(e) {

    },
    setTextContent(content, type = "string") {
      if (content === "") {
        //置空div输入框的值
        this.$refs.textarea.textContent = "";
        this.inputTextContent = ''
        return;
      }
      const textareaRef = this.$refs.textarea;
      const doc = textareaRef.ownerDocument || textareaRef.document;
      const _v = doc.defaultView || doc.parentWindow;
      const _selection = _v.getSelection();
      const createTributeEle = (c) => {
        let oFragment = document.createElement("span");
        oFragment.setAttribute("contenteditable", false);
        oFragment.textContent = `${c}`;
        return oFragment;
      };
      if (
        _selection &&
        _selection.baseNode &&
        (_selection.baseNode.className === "edit-textarea" ||
          _selection.baseNode.parentNode.className === "edit-textarea")
      ) {
        const range = _selection.getRangeAt(0);
        if (!range.isCollapsed) {
          range.deleteContents();
        }
        let oFragment;
        if (isEmpty(content) && "string" === type) {
          oFragment = range.createContextualFragment(content); // 创建一个需要添加的range片段
        } else {
          oFragment = createTributeEle(content);
        }
        let oLastNode = oFragment.lastChild; // 获取text节点1234
        if (oFragment instanceof Element) {
          oLastNode = oFragment;
        }
        range.insertNode(oFragment); // 在range处插入
        if (oLastNode) {
          range.setEndAfter(oLastNode); // 设置光标在插入的位置
          range.setStartAfter(oLastNode); // 设置光标在插入的位置
        }
        _selection.removeAllRanges(); // 去除之前的选择range
        _selection.addRange(range); // 将range设置为当前的range
      } else {
        const range = document.createRange();
        let oFragment;
        if (isEmpty(content) && "string" === type) {
          oFragment = range.createContextualFragment(content); // 创建一个需要添加的range片段
        } else {
          oFragment = createTributeEle(content);
        }
        textareaRef.appendChild(oFragment);
        range.collapse(true);
        range.setStartAfter(textareaRef.lastChild ?? textareaRef); // 设置光标在插入的位置
        _selection.removeAllRanges(); // 去除之前的选择range
        _selection.addRange(range); // 将range设置为当前的range
      }
    },
    // 键盘按下监听事件
    keydownEvent(e) {
      // 按下回车键
      if (e.keyCode == 13) {
        if (this.$refs.textarea.textContent == "") {
          e.preventDefault();
          return;
        }
        if ("Ctrl+Enter" === this.shortCutKey && (e.ctrlKey || e.metaKey)) {
          console.log("ctrl+enter键发送消息", this.shortCutKey)
          this.sendMsg();
          e.preventDefault();
        }
        if ("Enter" === this.shortCutKey && e.ctrlKey) {
          //如果设置的是回车键为发送消息  但是按下的是回车键+ctrl同时触发了并且
          const br = document.createElement("br")
          this.$refs.textarea.appendChild(br)
          //移动光标到最后位置
          var sel = window.getSelection();
          var range = document.createRange();
          range.selectNodeContents(this.$refs.textarea);
          range.collapse(false);
          sel.removeAllRanges();
          sel.addRange(range);
        } else {
          //如果仅仅是enter键触发了 
          if ("Enter" === this.shortCutKey) {
            console.log("enter键发送消息", this.shortCutKey)
            const node = document.getElementsByClassName("tribute-container")[0];
            if (node) {
              // 如果@人弹出tribute列表时回车，先做@人选择动作，阻止消息发送
              if (node.style.display === "block") {
                return;
              }
            }

            this.sendMsg(e);
            e.preventDefault();
          }
        }

      }
    },
    // 按钮发送消息
    sendMsg(e) {
      let currentTime = new Date().getTime();
      if (this.sendtime > 0) {
        // 判断 1秒内只能发送一条消息
        if (currentTime - this.sendtime < this.interval) {
          e.preventDefault();
          return false;
        }
      }
      if (!this.checkCanSendMsg()) {
        return;
      }
      //最外面的div输入框总内容 跟inputText的内容同时存在 并且都不能为空
      if (this.$refs.textarea.textContent && this.$refs.textarea.textContent.length && !!this.inputTextContent) {
        //如果是回复消息的对象有 基于会话id来存储回复的那条消息对象  就发送回复消息 
        // if (!!this.sessionInfo && !!this.msgRecordCopyItem[this.sessionInfo.targetId]) {
        //   //发送回复消息 
        //   this.sendReplyMsg(this.inputTextContent)
        // }
        //如果是文本消息
        this.sendTextMsg(this.inputTextContent);
        this.clearReplyMsgItem() //清空回复消息的item
        this.clearEditMapValueBySessionId() //清空当前edit缓存
        //置空div输入框的值
        this.$refs.textarea.textContent = "";
        this.sendtime = currentTime;
      }
    },
    checkCanSendMsg() {
      // 已退群或者已解散
      if (
        2 == this.sessionInfo.type &&
        (!this.currentGroupInfo.inGroup || this.currentGroupInfo.isDissolve)
      ) {

        return false;
      }

      // 处理发言频率限制
      if (
        2 == this.sessionInfo.type &&
        1 === this.currentGroupInfo.speakFrequencyRestrict &&
        !this.currentGroupInfo.isGroupLeader &&
        !this.currentGroupInfo.isManager
      ) {
        const lastMsgTimestamp = this.groupMsgMap[this.sessionInfo.targetId];
        if (lastMsgTimestamp && Date.now() - (lastMsgTimestamp ?? 0) < 10000) {
          this.$ipcInvoke(ipcApiRoute.insertSysMessageRecord, {
            sendType: this.sessionInfo.type === 1 ? "PRIVATE" : "GROUP",
            targetId: this.sessionInfo.targetId,
            content: "%lang-sendFrequency-lang%",
          });
        } else {
          this.$store.dispatch("UPDATE_GROUP_MSG_MAP", {
            groupId: this.sessionInfo.targetId,
            timestamp: Date.now(),
          });
        }
      }

      // 处理禁言(只针对普通用户)
      if (
        2 == this.sessionInfo.type &&
        !this.currentGroupInfo.isGroupLeader &&
        !this.currentGroupInfo.isManager
      ) {
        // 查询当前用户是否被禁言了
        const my = this.groupMemberList.find(
          (item) => item.userId === this.userId
        );
        if (my && my.muteStatus) {

          return false;
        }

        // 如果开启了全员禁言
        if (1 == this.currentGroupInfo.muteStatus) {
          this.$ipcInvoke(ipcApiRoute.insertSysMessageRecord, {
            sendType: this.sessionInfo.type === 1 ? "PRIVATE" : "GROUP",
            targetId: this.sessionInfo.targetId,
            content: "%lang-groupDisable-lang%",
          });
          return false;
        }
      }
      return true;
    },

    // 发送撤回消息
    sendReplyMsg(content) {
      const params = {
        msgSendType: this.sessionInfo.type === 1 ? "PRIVATE" : "GROUP",
        targetId: this.sessionInfo.targetId,
        text: content,
        msgType: "QX:Reply",
      };
      //如果是群聊 构建群聊参数
      if (this.sessionInfo.type === 2) {
        // 群聊
        const pattern = /@(.+?)\s/g;
        const str = content + " ";
        const ats = str
          .match(pattern)
          ?.map((item) => item.slice(1, item.length - 1));

        if (ats) {
          const temp = this.groupMemberList.find(
            (item) => item?.userId === this.userId
          );
          let isLeader = false;
          if (temp.isLeader) {
            isLeader = true;
          }
          const atsIds = [];
          for (let i = 0; i < ats.length; i++) {
            if (ats[i] === this.$t("everyone") && isLeader) {
              atsIds.push("-1");
            } else {
              const member = this.groupMemberList.find(
                (item) =>
                  ats[i] !== this.$t("everyone") && ats[i] === item.nickname
              );
              if (member) {
                atsIds.push(member.userId);
              }
            }
          }
          params.atTos = atsIds;
        }
      }
      console.log("输出回复消息参数", JSON.stringify(params))
      //this.$emit("send", params);
    },

    // 发送文本消息
    sendTextMsg(content) {

    },
    // 选择图片文件后回调方法
    uploadImageChange(e) {

    },

    uploadFileChange(e) {

    },

    // 选择文件回调事件
    uploadFiles(fileList) {

    },

    // 打开图片查看器
    openImageViewer(file) {

    },

    // 确认上传图片消息回调事件
    confirmUploadImage(img) {

    },

    // 选中表情包回调事件
    selecteEmoticon(data) {

    },
    // vue-tribute @没匹配到人时的回调
    noMatchFound() {
      console.log("noMatchFound");
      const node = document.getElementsByClassName("tribute-container")[0];
      assList.add("tribute-empty");
    },
  },
};
</script>
<style scoped lang="less" >
.max-container {
  height: 100%;
  .editor-container {
    // height: 200px;
    height: 100%;
    width: 100%;
    position: relative;
    display: flex;
    flex-direction: column;
  }

  .editor-container .toolbar {
    line-height: 35px;
    // border-bottom: 1px solid #f5f0f0;
    //border-top: 1px solid #f5f0f0;
  }

  .editor-container .toolbar li {
    list-style: none;
    float: left;
    width: 35px;
    margin-left: 3px;
    cursor: pointer;
    text-align: center;
    line-height: 35px;
    position: relative;
    color: #8d8d8d;

  }

  .editor-container .toolbar li .tip-title {
    display: none;
    position: absolute;
    top: 38px;
    left: 0px;
    height: 26px;
    line-height: 26px;
    background-color: rgba(31, 35, 41, 0.9);
    color: white;
    min-width: 30px;
    font-size: 10px;
    padding: 0 5px;
    border-radius: 2px;
    white-space: pre;
    text-align: center;
    user-select: none;
    z-index: 1;
  }

  .editor-container .toolbar li:hover .tip-title {
    display: block;
  }

  li.active {
    background-color: #f7f5f5;
  }

  .editor-container .toolbar li:hover {
    background-color: #f7f5f5;
  }

  .editor-container .toolbar .text-tips {
    float: right;
    margin-right: 15px;
    font-size: 12px;
    color: #ccc;
  }

  .editor-container .toolbar .text-tips i {
    font-size: 14px;
    cursor: pointer;
    margin-left: 5px;
    color: rgb(255, 181, 111);
  }

  .editor-container .textarea {
    // overflow: hidden;
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1;
    padding-bottom: 30px;
    box-sizing: border-box;
    font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
      "Microsoft YaHei", "微软雅黑", Arial, sans-serif;

    .vue-tribute {
      height: 100%;

      .edit-textarea {
        width: 100%;
        font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
          "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
        padding: 5px 10px 0;
        font-size: 14px;
        border: 0 none;
        outline: none;
        overflow-y: auto;
        flex: 1;
      }

      .edit-textarea::-webkit-scrollbar {
        width: 4px;
        height: 1px;
      }

      .edit-textarea::-webkit-scrollbar-thumb {
        background: #d5cfcf;
      }

      .edit-textarea::-webkit-scrollbar-track {
        background: #ededed;
      }

      .edit-textarea::-webkit-input-placeholder {
        color: #dccdcd;
        font-size: 12px;
        font-weight: 400;
      }
    }

    .edit-textarea::-webkit-scrollbar {
      width: 4px;
      height: 1px;
    }

    .edit-textarea::-webkit-scrollbar-thumb {
      background: #d5cfcf;
    }

    .edit-textarea::-webkit-scrollbar-track {
      background: #ededed;
    }

    .edit-textarea::-webkit-input-placeholder {
      color: #dccdcd;
      font-size: 12px;
      font-weight: 400;
    }

    .edit-textarea {
      width: 100%;
      font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
        "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
      padding: 5px 10px 0;
      font-size: 14px;
      border: 0 none;
      outline: none;
      overflow-y: auto;
      flex: 1;
    }

    .send-button {
      width: 100%;
      height: 28px;
      text-align: right;
      margin-bottom: 40px;

      .send-button-text {
        display: inline-block;
        width: 60px;
        line-height: 28px;
        background: #e8f1ff;
        border-radius: 2px;
        cursor: pointer;
        color: rgb(88, 126, 250);
        text-align: center;
        margin: 0px 16px 0px 0;
      }
    }
  }
}


/* 编辑器文档说明 --- end */

.ui-ul-inline-block {
  padding-left: 0;

  li {
    img {
      width: 20px;
      height: 20px;
      vertical-align: middle;
    }
  }
}
.ui-file-box {
  position: relative;
  .ui-file-con {
    position: relative;
    z-index: 1;
  }

  .ui-file-input {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 2;
    opacity: 0;
  }
}
</style>
